#include "Cube.h"

Cube::Cube()
:forward(0.0f, 0.0f, 0.0f),
left(0.0f, 0.0f, 0.0f),
angleY(0),
speed(5.0f),
mFX(0),
errors(0)
{
	BuildVertexBuffer();
	BuildIndexBuffer();

	HR(D3DXCreateTextureFromFile( gd3dDevice, "Textures/crate.jpg", &mTex));

	HR(D3DXCreateEffectFromFile( gd3dDevice
							, "TransformTex.fx"
							, 0, 0,
							D3DXSHADER_DEBUG
							, 0, &mFX
							, &errors));
	if(errors)
		MessageBox(0, (char*)errors->GetBufferPointer(), 0, 0);

	mhWVP = mFX->GetParameterByName(0, "gWVP");
	mhTex0 = mFX->GetParameterByName(0, "gTex");
	mhTech = mFX->GetTechniqueByName("TransformTech");

	mFX->SetTexture(mhTex0, mTex);
}

Cube::~Cube()
{
	ReleaseCOM(mVB);
	ReleaseCOM(mIB);
}

void Cube::OnResetDevice()
{
	mFX->OnResetDevice();
}

void Cube::OnLostDevice()
{
	mFX->OnLostDevice();
}

void Cube::Draw(D3DXMATRIX &mView, D3DXMATRIX &mProj)
{
	HR(gd3dDevice->SetStreamSource(0, mVB,0, sizeof(VertexTex)));
	HR(gd3dDevice->SetIndices(mIB));
	HR(gd3dDevice->SetVertexDeclaration(VertexTex::decl));

	HR(mFX->SetTechnique(mhTech));
	
	D3DXMATRIX Tf, Tl, R;
	D3DXMatrixTranslation(&Tf, forward.x, forward.y, forward.z);
	D3DXMatrixTranslation(&Tl, left.x, left.y, left.z);
	D3DXMatrixRotationY(&R, angleY);

	UINT numPasses = 0;
	HR(mFX->Begin(&numPasses, 0));
	for(int i = 0; i < numPasses; ++i)
	{
		HR(mFX->BeginPass(i));

		HR(mFX->SetMatrix(mhWVP, &(R * Tf * Tl * mView * mProj)));
		mFX->CommitChanges();

		HR(gd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 24, 0, 12));

		HR(mFX->EndPass());
	}

	//gd3dDevice->SetTransform(D3DTS_WORLD, &(R * Tf * Tl));

	HR(mFX->End());
}

void Cube::Update(float dt)
{
	D3DXVECTOR3 inputDirection = D3DXVECTOR3( (gDInput->keyDown(DIK_A)?1:0) + (gDInput->keyDown(DIK_D)?-1:0)
											, 0
											, (gDInput->keyDown(DIK_W)?1:0) + (gDInput->keyDown(DIK_S)?-1:0));

	angleY += ((gDInput->keyDown(DIK_Q)?-1:0) + (gDInput->keyDown(DIK_E)?1:0)) * speed * dt;

	forward.x += inputDirection.z * sin(angleY) * speed * dt;
	forward.z += inputDirection.z * cos(angleY) * speed * dt;

	left.x += inputDirection.x * sin(angleY - D3DX_PI/2) * speed * dt;
	left.z += inputDirection.x * cos(angleY - D3DX_PI/2) * speed * dt;
}

void Cube::BuildVertexBuffer()
{
	// Create the vertex buffer.
	HR(gd3dDevice->CreateVertexBuffer(24 * sizeof(VertexTex), D3DUSAGE_WRITEONLY,
		0, D3DPOOL_MANAGED,	&mVB, 0));

	// Write box vertices to the vertex buffer.
	VertexTex* v = 0;
	HR(mVB->Lock(0, 0, (void**)&v, 0));

	// Fill in the front face vertex data.
	v[0] = VertexTex(-1.0f, -1.0f, -1.0f, 0.0f, 1.0f);
	v[1] = VertexTex(-1.0f,  1.0f, -1.0f, 0.0f, 0.0f);
	v[2] = VertexTex( 1.0f,  1.0f, -1.0f, 1.0f, 0.0f);
	v[3] = VertexTex( 1.0f, -1.0f, -1.0f, 1.0f, 1.0f);

	// Fill in the back face vertex data.
	v[4] = VertexTex(-1.0f, -1.0f, 1.0f, 1.0f, 1.0f);
	v[5] = VertexTex( 1.0f, -1.0f, 1.0f, 0.0f, 1.0f);
	v[6] = VertexTex( 1.0f,  1.0f, 1.0f, 0.0f, 0.0f);
	v[7] = VertexTex(-1.0f,  1.0f, 1.0f, 1.0f, 0.0f);

	// Fill in the top face vertex data.
	v[8]  = VertexTex(-1.0f, 1.0f, -1.0f, 0.0f, 1.0f);
	v[9]  = VertexTex(-1.0f, 1.0f,  1.0f, 0.0f, 0.0f);
	v[10] = VertexTex( 1.0f, 1.0f,  1.0f, 1.0f, 0.0f);
	v[11] = VertexTex( 1.0f, 1.0f, -1.0f, 1.0f, 1.0f);

	// Fill in the bottom face vertex data.
	v[12] = VertexTex(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f);
	v[13] = VertexTex( 1.0f, -1.0f, -1.0f, 0.0f, 1.0f);
	v[14] = VertexTex( 1.0f, -1.0f,  1.0f, 0.0f, 0.0f);
	v[15] = VertexTex(-1.0f, -1.0f,  1.0f, 1.0f, 0.0f);

	// Fill in the left face vertex data.
	v[16] = VertexTex(-1.0f, -1.0f,  1.0f, 0.0f, 1.0f);
	v[17] = VertexTex(-1.0f,  1.0f,  1.0f, 0.0f, 0.0f);
	v[18] = VertexTex(-1.0f,  1.0f, -1.0f, 1.0f, 0.0f);
	v[19] = VertexTex(-1.0f, -1.0f, -1.0f, 1.0f, 1.0f);

	// Fill in the right face vertex data.
	v[20] = VertexTex( 1.0f, -1.0f, -1.0f, 0.0f, 1.0f);
	v[21] = VertexTex( 1.0f,  1.0f, -1.0f, 0.0f, 0.0f);
	v[22] = VertexTex( 1.0f,  1.0f,  1.0f, 1.0f, 0.0f);
	v[23] = VertexTex( 1.0f, -1.0f,  1.0f, 1.0f, 1.0f);

	HR(mVB->Unlock());
}

void Cube::BuildIndexBuffer()
{
	// Create the vertex buffer.
	HR(gd3dDevice->CreateIndexBuffer(36 * sizeof(WORD),	D3DUSAGE_WRITEONLY,
		D3DFMT_INDEX16,	D3DPOOL_MANAGED, &mIB, 0));

	// Write box indices to the index buffer.
	WORD* i = 0;
	HR(mIB->Lock(0, 0, (void**)&i, 0));

	// Fill in the front face index data
	i[0] = 0; i[1] = 1; i[2] = 2;
	i[3] = 0; i[4] = 2; i[5] = 3;

	// Fill in the back face index data
	i[6] = 4; i[7]  = 5; i[8]  = 6;
	i[9] = 4; i[10] = 6; i[11] = 7;

	// Fill in the top face index data
	i[12] = 8; i[13] =  9; i[14] = 10;
	i[15] = 8; i[16] = 10; i[17] = 11;

	// Fill in the bottom face index data
	i[18] = 12; i[19] = 13; i[20] = 14;
	i[21] = 12; i[22] = 14; i[23] = 15;

	// Fill in the left face index data
	i[24] = 16; i[25] = 17; i[26] = 18;
	i[27] = 16; i[28] = 18; i[29] = 19;

	// Fill in the right face index data
	i[30] = 20; i[31] = 21; i[32] = 22;
	i[33] = 20; i[34] = 22; i[35] = 23;

	HR(mIB->Unlock());
}